#include "EchoSvrApp.h"
#include <time.h>
#define NET_RECV_BUF_SIZE   4*1024
#define NET_SEND_BUF_SIZE   4*1024
#ifdef _WIN32
#include "stdafx.h"
#include <process.h>

CEchoSvrApp::CEchoSvrApp(void)
{
    m_hThread = NULL;
    m_hNetDll = NULL;

    m_poNetMgr = NULL;
    m_bTerminate = true;
    m_hListener = NULL;
}

bool CEchoSvrApp::Start( UINT16 wPort )
{
    if (!__Init())
    {
        return false;
    }

    unsigned dwAddr;
    m_bTerminate = false;
    m_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, this, 0, &dwAddr);
    if (NULL == m_hThread)
    {
        return false;
    }

    return true;
}

void CEchoSvrApp::Stop( void )
{
    m_bTerminate = true;
    WaitForSingleObject(m_hThread, INFINITE);
    CloseHandle(m_hThread);
    m_hThread = NULL;
    __UnInit();
}

unsigned __stdcall CEchoSvrApp::ThreadFunc( void* pVoid )
{
    CEchoSvrApp* poEchoSvrApp = (CEchoSvrApp*)pVoid;
    poEchoSvrApp->__OnExecute();
    return 0;
}

bool CEchoSvrApp::__Init( void )
{
#ifdef _DEBUG
    m_hNetDll = ::LoadLibrary("netd.dll");
#else
    m_hNetDll = ::LoadLibrary("net.dll");
#endif

    if (NULL == m_hNetDll)
    {
        return false;
    }

    pfn_CreateNetManager pfunc = (pfn_CreateNetManager)::GetProcAddress(m_hNetDll, "CreateNetManager");

    if (NULL == pfunc)
    {
        return false;
    }

    m_poNetMgr = pfunc(NET_IO_COMPLETEPORT, this, net_libversion);
    //    m_poNetMgr = CreateNetManager(NET_IO_COMPLETEPORT, this, net_libversion);

    if (NULL == m_poNetMgr)
    {
        return false;
    }

    m_hListener = m_poNetMgr->Listen("0",8888, NET_RECV_BUF_SIZE, NET_SEND_BUF_SIZE, &m_oPacketParser);
    if (NULL == m_hListener)
    {
        return false;
    }

    m_dwSessionCount = 0;
    m_dwErrorCount = 0;
    m_dwEstablishCount = 0;
    m_dwTerminateCount = 0;
    m_qwByteRecv = 0;
    m_qwByteSend = 0;
    m_dwSendFailCount = 0;
    m_mapModuleError.clear();
    m_mapSystemError.clear();
    m_dwStartSec = (UINT32)time(NULL);
    return true;
}

void CEchoSvrApp::__UnInit( void )
{
	if (NULL != m_hListener)
	{
		m_poNetMgr->CloseNetHandle(m_hListener);
		m_hListener = NULL;
	}

	if (NULL != m_poNetMgr)
	{
		m_poNetMgr->Release();
		m_poNetMgr = NULL;
	}

    if (NULL != m_hNetDll)
    {
        FreeLibrary(m_hNetDll);
    }
}

void CEchoSvrApp::__OnExecute( void )
{
    static UINT32 dwlast = GetTickCount();

	while (!m_bTerminate)
	{
		if (!m_poNetMgr->Run(-1))
		{
            Sleep(1);
		}

        if ((GetTickCount() - dwlast) > 1000)
        {
            CheckSessionCount();
            dwlast = GetTickCount();
        }
	}
}

#else

#include <pthread.h>
#include <signal.h>
#include "timehelp.h"

CEchoSvrApp::CEchoSvrApp(void)
{
    m_stThread = 0;

    m_poNetMgr = NULL;
    m_bTerminate = true;
    m_hListener = NULL;
}

bool CEchoSvrApp::Start( UINT16 wPort )
{
    if (!__Init())
    {
        return false;
    }

    m_bTerminate = false;
    if (0 != pthread_create(&m_stThread, NULL, ThreadFunc, this))
    {
        m_stThread = 0;
        return false;
    }
    return true;
}

void CEchoSvrApp::Stop( void )
{
    m_bTerminate = true;
    pthread_join(m_stThread, NULL);
    __UnInit();
}

void* CEchoSvrApp::ThreadFunc(void* arg)
{
    CEchoSvrApp* poEchoSvrApp = (CEchoSvrApp*)arg;
    poEchoSvrApp->__OnExecute();
}

bool CEchoSvrApp::__Init( void )
{
    m_poNetMgr = CreateNetManager(NET_IO_EPOLL, this, net_libversion);

    if (NULL == m_poNetMgr)
    {
        return false;
    }

    m_hListener = m_poNetMgr->Listen("0",8888, NET_RECV_BUF_SIZE, NET_SEND_BUF_SIZE, &m_oPacketParser);
    if (NULL == m_hListener)
    {
        return false;
    }

    m_dwSessionCount = 0;
    m_dwErrorCount = 0;
    m_dwEstablishCount = 0;
    m_dwTerminateCount = 0;
    m_qwByteRecv = 0;
    m_qwByteSend = 0;
    m_dwSendFailCount = 0;
    m_mapModuleError.clear();
    m_mapSystemError.clear();
    m_dwStartSec = (UINT32)time(NULL);
    return true;
}

void CEchoSvrApp::__UnInit( void )
{
	if (NULL != m_hListener)
	{
		m_poNetMgr->CloseNetHandle(m_hListener);
		m_hListener = NULL;
	}

	if (NULL != m_poNetMgr)
	{
		m_poNetMgr->Release();
		m_poNetMgr = NULL;
	}
}

void CEchoSvrApp::__OnExecute( void )
{
    static UINT32 dwlast = GetTickCount();

	while (!m_bTerminate)
	{
		if (!m_poNetMgr->Run(-1))
		{
            usleep(1);
		}

        if ((GetTickCount() - dwlast) > 1000)
        {
            CheckSessionCount();
            dwlast = GetTickCount();
        }
	}
}
#endif

void CEchoSvrApp::OnEstablish( HNETHANDLE hHandle, HSESSION hSession )
{
    ++m_dwSessionCount;
    ++m_dwEstablishCount;
    m_mapClient[hSession] = 0;
    m_mapClientCount[hSession] = 0;
    //m_iPkgCount = 0;
}

void CEchoSvrApp::OnTerminate( HSESSION hSession )
{
    --m_dwSessionCount;
    ++m_dwTerminateCount;
    m_mapClientCount.erase(hSession);
    m_mapClient.erase(hSession);
}

void CEchoSvrApp::OnError( HNETHANDLE hHandle, HSESSION hSession, INT32 iModuleError, INT32 iSystemError )
{
    ++m_dwErrorCount;

    if (iModuleError == NET_SYSTEM_ERROR || iModuleError == NET_CONNECT_FAIL)
    {
        std::map<INT32, UINT32>::iterator itError = m_mapSystemError.find(iSystemError);
        if (itError == m_mapSystemError.end())
        {
            m_mapSystemError[iSystemError] = 1;
        }
        else
        {
            m_mapSystemError[iSystemError] = itError->second +1;
        }
    }
    else
    {
        std::map<INT32, UINT32>::iterator itError = m_mapModuleError.find(iModuleError);
        if (itError == m_mapModuleError.end())
        {
            m_mapModuleError[iModuleError] = 1;
        }
        else
        {
            m_mapModuleError[iModuleError] = itError->second +1;
        }
    }
}

void CEchoSvrApp::OnRecv( HSESSION hSession, const char* pData, const INT32 iLen )
{
    //Sleep(1000);
    //++m_iPkgCount;
    m_mapClientCount[hSession] = 0;
    CClientMap::iterator it = m_mapClient.find(hSession);
    if (it == m_mapClient.end())
    {
        printf("Can't find HSession 0x%08x\r\n", hSession);
    }
    else
    {
        UINT32 dwIdx = it->second;

        if ((dwIdx+1) != *(UINT32*)(pData+iLen-4))
        {
            __FailPkgLog(pData, iLen, 0);
            printf("Tick= %d last Recv Idx= %d, now Recv Idx= %d\r\n", GetTickCount(), it->second, *(UINT32*)(pData+iLen-4));
        }
        m_mapClient[hSession] = dwIdx+1;
    }

    m_qwByteRecv += iLen;
    if (m_poNetMgr->Send(hSession, pData, iLen))
    {
        m_qwByteSend += iLen;
    }
    else
        ++m_dwSendFailCount;
}

void CEchoSvrApp::PrintTestInfo( void )
{
    UINT32 dwElapseSec = (UINT32)time(NULL) - m_dwStartSec;

    printf("**************************************************\n");
    printf("Session = %u %u/s\n", m_dwSessionCount, m_dwSessionCount/dwElapseSec);
    printf("Establish = %u %u/s\n", m_dwEstablishCount, m_dwEstablishCount/dwElapseSec);
    printf("Terminate = %u %u/s\n", m_dwTerminateCount, m_dwTerminateCount/dwElapseSec);
    printf("Error = %u %u/s\n", m_dwErrorCount, m_dwErrorCount/dwElapseSec);
    printf("Recv Byte = %llu %llu/s\n", m_qwByteRecv, m_qwByteRecv/dwElapseSec);
    printf("Send Byte = %llu %llu/s\n", m_qwByteSend, m_qwByteSend/dwElapseSec);
    printf("Send Fail = %u %u/s\n", m_dwSendFailCount, m_dwSendFailCount/dwElapseSec);
    
    std::map<INT32, UINT32>::iterator itModuleError = m_mapModuleError.begin();
    while (itModuleError != m_mapModuleError.end())
    {
        switch(itModuleError->first)
        {
        case -3:
            printf("Module Error NET_SEND_OVERFLOW Count = %u\n", itModuleError->second);
        	break;
        case -2:
            printf("Module Error NET_RECV_OVERFLOW Count = %u\n", itModuleError->second);
            break;
        case -1:
            printf("Module Error NET_PACKET_ERROR Count = %u\n", itModuleError->second);
            break;
        default:
            break;
        }
        ++itModuleError;
    }

    std::map<INT32, UINT32>::iterator itSystemError = m_mapSystemError.begin();
    while (itSystemError != m_mapSystemError.end())
    {
        printf("System Error Code = %u, Count = %u\n", itSystemError->first, itSystemError->second);
        ++itSystemError;
    }
}

void CEchoSvrApp::CheckSessionCount( void )
{
    CClientMap::iterator it = m_mapClientCount.begin();
    while (it != m_mapClientCount.end())
    {
        it->second = it->second+1;

        if (it->second > 10)
        {
            m_poNetMgr->DisConnect(it->first);
        }
        ++it;
    }
}

void CEchoSvrApp::__FailPkgLog( const char* pData, const INT32 iLen, INT32 iType )
{
    FILE* pFile = fopen("FailPkg.log", "ab");
    if (NULL == pFile)
    {
        return;
    }

    fprintf(pFile, "\r\nRecv pkg:\r\n");
    fprintf(pFile, "PkgSize = %d\r\n", *(INT32*)(pData));
    fprintf(pFile, "HSession=0x%08x\r\n", *(UINT32*)(pData+sizeof(INT32)));
    fprintf(pFile, "Socket=%d\r\n", *(UINT32*)(pData+sizeof(INT32)+sizeof(UINT32)));
    fprintf(pFile, "PkgIndex=%d\r\n", *(UINT32*)(pData+iLen -4));
    for (INT32 i = 0; i < iLen; i++)
    {
        fprintf(pFile, "0x%02x ", (unsigned char)pData[i]);
    }


    fclose(pFile);
}

INT32 CPacketParser::ParsePacket( const char* pData, const INT32 dwLen )
{
    if (dwLen < sizeof(UINT32))
    {
        return 0;
    }

    INT32 dwPkglen = *(UINT32*)pData;

    if (dwPkglen > dwLen)
    {
        return 0;
    }

    return dwPkglen;
    //return dwLen;
}

CEchoSvrApp::~CEchoSvrApp(void)
{
}